﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using newtelligence.DasBlog.Runtime;
using dasBlog.Storage;

namespace dasBlog.Services.Interop
{
    class StorageBusLoggingService : ILoggingDataService
    {
        private ContextUri scopeUri;
        private ContextUri eventsUri;
        private ContextUri logUri;

        public StorageBusLoggingService(string scopeName)
        {
            this.scopeUri = new ContextUri(scopeName);
            this.eventsUri = new ContextUri(scopeName, PathSegmentName.Events);
            this.logUri = new ContextUri(scopeName, PathSegmentName.Trackings);
        }

        public LogDataItemCollection GetReferralsForDay(DateTime date)
        {
            return GetLogItems(date, "R");
        }
        
        public void AddReferral(LogDataItem logItem)
        {
            AddLogItem(logItem, "R");
        }
                
        public LogDataItemCollection GetClickThroughsForDay(DateTime date)
        {
            return GetLogItems(date, "C");
        }

        public void AddClickThrough(LogDataItem logItem)
        {
            AddLogItem(logItem, "C");
        }

        public LogDataItemCollection GetAggregatorBugHitsForDay(DateTime date)
        {
            return GetLogItems(date, "A");
        }

        public void AddAggregatorBugHit(LogDataItem logItem)
        {
            AddLogItem(logItem, "A");
        }

        public LogDataItemCollection GetCrosspostReferrersForDay(DateTime date)
        {
            return GetLogItems(date, "X");
        }

        public void AddCrosspostReferrer(LogDataItem logItem)
        {
            AddLogItem(logItem, "X");
        }

        public EventDataItemCollection GetEventsForDay(DateTime date)
        {
            IStorageNode storageNode = StorageBus.Current.FindNode(eventsUri);
            return new EventDataItemCollection(
                (from entry in SerializationTools<EventEntry>.DeserializeList(
                      storageNode.Select(null,
                                        eventsUri.ToString(),
                                        ContextMatch.Exact,
                                        new DateRangeQueryDescription(date.Date.ToUniversalTime(), date.Date.ToUniversalTime().AddDays(1).AddMilliseconds(-1)),
                                        null))
                 orderby entry.Time ascending
                 select new EventDataItem
                 {
                      EventCode = int.Parse(entry.Code),
                      EventTimeUtc = entry.Time,
                      HtmlMessage = entry.Message
                 }).ToArray());
        }

        public void AddEvent(EventDataItem eventData)
        {
            IStorageNode node = StorageBus.Current.FindNode(eventsUri);
            if (node != null)
            {
                EventEntry logEntry = new EventEntry
                {
                     Code = eventData.EventCode.ToString(),
                     Message = eventData.HtmlMessage,
                     Time = eventData.EventTimeUtc
                };
                node.Add(eventsUri.ToString(),
                         SerializationTools<EventEntry>.ToXmlElement(logEntry),
                         null);
            }
        }

        private void AddLogItem(LogDataItem logItem, string type)
        {
            IStorageNode node = StorageBus.Current.FindNode(logUri);
            if (node != null)
            {
                LogEntry logEntry = new LogEntry
                {
                    TrackingType = type,
                    UrlReferrer = logItem.UrlReferrer,
                    UserAgent = logItem.UserAgent,
                    UserDomain = logItem.UserDomain,
                    UrlRequested = logItem.UrlRequested,
                    RequestTime = logItem.RequestedUtc
                };
                node.Add(logUri.ToString(),
                         SerializationTools<LogEntry>.ToXmlElement(logEntry),
                         null);
            }
        }

        private LogDataItemCollection GetLogItems(DateTime date, string type)
        {
            IStorageNode storageNode = StorageBus.Current.FindNode(logUri);
            return new LogDataItemCollection(
                (from entry in SerializationTools<LogEntry>.DeserializeList(
                      storageNode.Select(null,
                                        logUri.ToString(),
                                        ContextMatch.Exact,
                                        new DateRangeAndTagQueryDescription(date.Date.ToUniversalTime(), date.Date.ToUniversalTime().AddDays(1).AddMilliseconds(-1), type),
                                        null))
                 orderby entry.RequestTime ascending
                 select new LogDataItem
                 {
                      RequestedUtc = entry.RequestTime,
                      UrlReferrer = entry.UrlReferrer,
                      UrlRequested = entry.UrlRequested,
                      UserAgent = entry.UserAgent,
                      UserDomain = entry.UserDomain,
                 }).ToArray());
        }

    }
}
